package top.yzlin.dblock.component;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.yzlin.dblock.inter.StatementOperateEvent;

import java.util.LinkedList;
import java.util.concurrent.Executor;

/**
 * @author yzlin
 */
@Component
public class DatabaseOperateQueue implements Runnable, InitializingBean {
    private JdbcConnectionOperate jdbcConnectionOperate;
    private final LinkedList<StatementOperateEvent> operateEventList = new LinkedList<>();
    private Executor executor;
    private RedisLockFactory redisLockFactory;
    private RedisLock redisLock;

    @Autowired
    public void setRedisLockFactory(RedisLockFactory redisLockFactory) {
        this.redisLockFactory = redisLockFactory;
    }

    @Autowired
    public void setExecutor(Executor executor) {
        this.executor = executor;
    }

    @Autowired
    public void setJdbcConnectionOperate(JdbcConnectionOperate jdbcConnectionOperate) {
        this.jdbcConnectionOperate = jdbcConnectionOperate;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        redisLock = redisLockFactory.newRedisLock("dbConnection");
    }

    public boolean addDatabaseOperate(StatementOperateEvent operateEvent) {
        synchronized (operateEventList) {
            if (operateEventList.size() > 0) {
                return operateEventList.add(operateEvent);
            } else {
                boolean add = operateEventList.add(operateEvent);
                executor.execute(this);
                return add;
            }
        }
    }

    @Override
    public void run() {
        while (operateEventList.size() > 0) {
            redisLock.lock();
            jdbcConnectionOperate.performStatement(operateEventList.getFirst());
            redisLock.unlock();
            operateEventList.removeFirst();
        }
    }

}
